﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WcfClientTemplates.Templates;
using WcfClientTemplates.Test.Util;
using Raona.Code.Model;



namespace WcfClientTemplates.Test
{
    [TestClass]
    public class InterfacesTest
    {
        #region Generation Parameter (Private)

        private const string SPECIFIC_USINGS = @"
using AirProducts.Entities.Healthcare.General;
using AirProducts.Entities.Healthcare.Patients;
using AirProducts.Entities.Healthcare.Persons;
using AirProducts.Entities.Healthcare.Treatments;
using AirProducts.Entities.Healthcare.Users;
";
        private const string NAMESPACE_1 = "AirProducts.Services.Healthcare.Persons";
        private const string NAMESPACE_2 = "AirProducts.Services.Healthcare.Treatments";
        private const string SERVICE_CONTRACT_NAMESPACE = "http://www.airproducts.com/services";
        private const string INTERFACE_1 = "IPatientService";

        #endregion

        /// <summary>
        /// When no interface and no namespace are provided, the usings section is the only code generated
        /// </summary>
        [TestMethod]
        public void JustUsings()
        {
            string result = null;
            Interfaces interfaces = new Interfaces();
            InterfacesUsings interfacesUsings = new InterfacesUsings();
            interfacesUsings.SpecificUsings = InterfacesTest.SPECIFIC_USINGS;
            result = interfacesUsings.TransformText();

            ResultsHelper.AreEqual("JustUsings", result);
        }

        /// <summary>
        /// When a namespace is provided, check it is generated
        /// </summary>
        [TestMethod]
        public void OneNamespace()
        {
            string result1 = null;
            string result2 = null;
            
            Interfaces interfaces = new Interfaces();
            InterfacesUsings interfacesUsings = new InterfacesUsings();
            
            interfacesUsings.SpecificUsings = InterfacesTest.SPECIFIC_USINGS;
            result1 = interfacesUsings.TransformText();

            interfaces.Namespaces = new Namespace[] { new Namespace { Name = InterfacesTest.NAMESPACE_1 } };
            result2 = interfaces.TransformText();

            ResultsHelper.AreEqual("OneNamespace", result1 + result2);
        }

        /// <summary>
        /// An interface with no methods
        /// </summary>
        [TestMethod]
        public void EmptyInterface()
        {
            string result1 = null;
            string result2 = null;

            Interfaces interfaces = new Interfaces();
            InterfacesUsings interfacesUsings = new InterfacesUsings();
            
            interfacesUsings.SpecificUsings = InterfacesTest.SPECIFIC_USINGS;
            result1 = interfacesUsings.TransformText();
            
            Namespace ns = new Namespace { Name = InterfacesTest.NAMESPACE_1 };
            interfaces.Namespaces = new Namespace[] { ns };
            Interface itf = new Interface { Name = InterfacesTest.INTERFACE_1, ServiceContractNamespace = InterfacesTest.SERVICE_CONTRACT_NAMESPACE };
            ns.Interfaces = new List<Interface>(new Interface[] { itf });
            result2 = interfaces.TransformText();

            ResultsHelper.AreEqual("EmptyInterface", result1 + result2);
        }

        /// <summary>
        /// An interface with just one method
        /// </summary>
        [TestMethod]
        public void InterfaceWithOneMethod()
        {
            string result1 = null;
            string result2 = null;

            Interfaces interfaces = new Interfaces();
            InterfacesUsings interfacesUsings = new InterfacesUsings();
            
            interfacesUsings.SpecificUsings = InterfacesTest.SPECIFIC_USINGS;
            result1 = interfacesUsings.TransformText();

            Namespace ns = new Namespace { Name = InterfacesTest.NAMESPACE_1 };
            interfaces.Namespaces = new Namespace[] { ns };
            Interface itf = new Interface { Name = InterfacesTest.INTERFACE_1, ServiceContractNamespace = InterfacesTest.SERVICE_CONTRACT_NAMESPACE };
            Method method = new Method { Name = "GetPatients", OverloadedName = "GetPatients1", ReturnType = "Raona.QueryResult<AirProducts.Entities.Healthcare.Patients.PatientCollection>" };
            Parameter[] parameters = new Parameter[] {
                new Parameter { Name = "properties", Type = "Raona.EntityModel.PropertyCollection" },
                new Parameter { Name = "filter", Type = "Raona.EntityModel.FilterCollection" },
                new Parameter { Name = "order", Type = "Raona.EntityModel.OrderCollection" },
                new Parameter { Name = "pageInfo", Type = "Raona.PageInfo" },
                new Parameter { Name = "logInfo", Type = "Raona.Logs.LogInfo" }
            };
            method.Parameters = new List<Parameter>(parameters);
            itf.AddMethod(method);
            ns.Interfaces = new List<Interface>(new Interface[] { itf });
            result2 = interfaces.TransformText();

            ResultsHelper.AreEqual("InterfaceWithOneMethod", result1 + result2);
        }

        /// <summary>
        /// An interface with just more than one method
        /// </summary>
        [TestMethod]
        public void InterfaceWithTwoMethods()
        {
            string result1 = null;
            string result2 = null;
            
            Interfaces interfaces = new Interfaces();
            InterfacesUsings interfacesUsings = new InterfacesUsings();

            interfacesUsings.SpecificUsings = InterfacesTest.SPECIFIC_USINGS;
            result1 = interfacesUsings.TransformText();

            Namespace ns = new Namespace { Name = InterfacesTest.NAMESPACE_1 };
            interfaces.Namespaces = new Namespace[] { ns };
            Interface itf = new Interface { Name = InterfacesTest.INTERFACE_1, ServiceContractNamespace = InterfacesTest.SERVICE_CONTRACT_NAMESPACE };
            Method method1 = new Method { Name = "GetPatients", OverloadedName = "GetPatients1", ReturnType = "Raona.QueryResult<AirProducts.Entities.Healthcare.Patients.PatientCollection>" };
            Parameter[] parameters1 = new Parameter[] {
                new Parameter { Name = "properties", Type = "Raona.EntityModel.PropertyCollection" },
                new Parameter { Name = "filter", Type = "Raona.EntityModel.FilterCollection" },
                new Parameter { Name = "order", Type = "Raona.EntityModel.OrderCollection" },
                new Parameter { Name = "pageInfo", Type = "Raona.PageInfo" },
                new Parameter { Name = "logInfo", Type = "Raona.Logs.LogInfo" }
            };
            method1.Parameters = new List<Parameter>(parameters1);
            Method method2 = new Method { Name = "GetPatientFullInformation", OverloadedName = "GetPatientFullInformation", ReturnType = "Raona.Serialization.XResult<AirProducts.Entities.Healthcare.Patients.Patient>" };
            Parameter[] parameters2 = new Parameter[] {
                new Parameter { Name = "patient", Type = "AirProducts.Entities.Healthcare.Patients.Patient" },
                new Parameter { Name = "logInfo", Type = "Raona.Logs.LogInfo" }
            };
            method2.Parameters = new List<Parameter>(parameters2);
            itf.AddMethods(new Method[] { method1, method2 });
            ns.Interfaces = new List<Interface>(new Interface[] { itf });
            result2 = interfaces.TransformText();

            ResultsHelper.AreEqual("InterfaceWithTwoMethods", result1 + result2);
        }

    }
}
